package com.xiaotu.spider.license.pageprocessor;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.xiaotu.common.exception.SpiderException;
import com.xiaotu.common.exception.SpiderExceptionCode;
import com.xiaotu.common.model.MOVPublicModel;
import com.xiaotu.common.util.CacheHandler;
import com.xiaotu.common.util.Constants;
import com.xiaotu.common.util.HtmlUtil;
import com.xiaotu.common.util.PageUtils;
import com.xiaotu.common.util.RegexUtils;
import com.xiaotu.common.util.StringUtil;
import com.xiaotu.spider.AUrlPageProcessor;

import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.selector.Html;
import us.codecraft.webmagic.utils.UrlUtils;

/**
 * 电影备案发行数据爬取
 *
 * @auther GaoHJ
 * @create 2017/10/9
 */
@Component("MOVPublicPageProcessor")
public class MOVPublicPageProcessor extends AUrlPageProcessor
{
    private static final String TABLE = "<table><tbody>%s</tbody></table>";

    private static final String MONTH_REG = String.format("(%s){4}年(%s){2}月", RegexUtils.REGEX_INTEGER, RegexUtils
            .REGEX_INTEGER);

    @Autowired
    private CacheHandler cacheHandler;

    @SuppressWarnings("unchecked")
    @Override
    public void process(Page page)
    {
        String pageType = this.getPageDataType(page);
        switch (pageType)
        {
            case Constants.PageDataType.URL:
                this.urlProcess(page);
                break;
            case Constants.PageDataType.TV_RECORD:
                this.tvProcess(page);
                break;
            default:
                this.listProcess(page);
                break;
        }
    }

    private void urlProcess(Page page)
    {
        List<String> linkList = page.getHtml().xpath("//div[@class='cc boxcontent']//li[@style]/a/@href").all();
        if (linkList == null || linkList.isEmpty())
            return;
        linkList.stream().filter(link -> !cacheHandler.hExists(Constants.DataRedisKey.MOV_Public_History.toString(),
                link)).forEach(link ->
        {
            PageUtils.addTargetRequest(page, link, PageUtils.getNewExtraMapFromPage(page,new String[]{URL_KEY},new Object[]{link}));
        });
    }

    private void listProcess(Page page)
    {
        Html html = page.getHtml();
        String title = html.xpath("//div[@class='heading']/text()").get();
        if (StringUtils.isEmpty(title))
            throw new SpiderException(SpiderExceptionCode.DataInvalideException);
        String month = RegexUtils.regexSearch(MONTH_REG, title);
        if (StringUtils.isEmpty(month))
            throw new SpiderException(SpiderExceptionCode.DataInvalideException);
        List<String> idList = html.xpath("//div[@class='ta1']/ul/li/@id").all();
        if (idList == null || idList.isEmpty())
            throw new SpiderException(SpiderExceptionCode.DataInvalideException);

        idList.stream().forEach(liId ->
        {
            List<String> trList = html.xpath("//div[@id='" + liId.replace("li", "div") + "']/table/tbody/tr").all();
            if (trList == null || trList.isEmpty()||trList.size()<2)
                throw new SpiderException(SpiderExceptionCode.DataInvalideException);
            String typeName = html.xpath("//div[@class='ta1']/ul/li[@id='" + liId + "']/span/text()").get();
            Map<String, Object> map = PageUtils.getNewExtraMapFromPage(page, new String[]{Constants.PageDataType
                    .TV_RECORD, "month", "type"}, new Object[]{Constants.PageDataType.TV_RECORD, month, typeName});
            trList.stream().skip(1).forEach(trStr ->
            {
                Html trObj = new Html(String.format(TABLE, trStr));
                String link = trObj.xpath("//td[2]/a/@onclick").get();
                link = RegexUtils.regexSearch("/[^']+", link);
                if (StringUtils.isEmpty(link))
                    throw new SpiderException(SpiderExceptionCode.DataInvalideException);
                PageUtils.addTargetRequest(page, UrlUtils.getHost(page.getUrl().toString()) + link, map);
            });
        });
    }


    private void tvProcess(Page page)
    {
        Html html = page.getHtml();
        String table = html.xpath("//table[@class='form']").get();
        if (StringUtils.isEmpty(table))
            throw new SpiderException(SpiderExceptionCode.DataInvalideException);
        Html tableObj = new Html(table);
        List<String> trList = tableObj.xpath("//tr").all();
        if (trList == null || trList.size() < 3)
            throw new SpiderException(SpiderExceptionCode.DataInvalideException);
        Html trObj = new Html(String.format(TABLE, trList.get(1)));

        List<String> baseList = new ArrayList<>(6);
        trObj.xpath("//td").all().forEach(tdStr -> baseList.add(HtmlUtil.delHTMLTag(tdStr)));

        trObj = new Html(String.format(TABLE, trList.get(2)));
        String introduction = HtmlUtil.delHTMLTag(trObj.xpath("//span").get());
        String month =(String) page.getRequest().getExtra("month");
        month =month.replace("年", "-").replace("月", "");
        
        page.putField(MOVPublicModel.class.getName(), new MOVPublicModel(Constants.TargetType.OTHER_TYPE_ID, baseList
                .get(1), StringUtil.nullToString(page.getRequest().getExtra("type")), baseList.get(2), baseList.get
                (0), StringUtil.nullToString(month), baseList.get(3), baseList.get(4),
                baseList.get(5), introduction));
        page.putField(URL_KEY,page.getRequest().getExtra(URL_KEY));
    }

    @Override
    protected String[] getStartRequestUrls()
    {
        return new String[]{"http://dy.chinasarft.gov.cn/html/www/catalog/0129dffcccb1015d402881cd29de91ec.html"};
    }

    @Override
    protected String getSpiderType()
    {
        return Constants.SpiderTaskType.MOV_PUBLIC;
    }

    @Override
    public String getPageDataType(Page page)
    {
        if (page.getUrl().toString().contains("http://dy.chinasarft.gov.cn/html/www/catalog"))
            return Constants.PageDataType.URL;
        if (page.getRequest().getExtra(Constants.PageDataType.TV_RECORD) != null)
            return Constants.PageDataType.TV_RECORD;
        return Constants.PageDataType.SEARCH_LIST;
    }

}
